package com.cci.kangdao.service.impl;

import com.cci.kangdao.dao.*;
import com.cci.kangdao.dao.model.CustomerEngineRelT;
import com.cci.kangdao.dao.model.OcrVehicleLicenseT;
import com.cci.kangdao.dao.model.UserChannelT;
import com.cci.kangdao.dao.model.UserT;
import com.cci.kangdao.service.SyncEsnAndUserId;
import com.cci.kangdao.utilTool.*;
import net.sf.json.JSONObject;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.message.BasicHeader;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @description: 【月度报告】实时更新ESN list
 * @author: joe
 * @company: CTY
 * @since: 2023/2/3 11:11
 * @version: V1.0
 **/
@Service("SyncEsnAndUserIdImpl")
public class SyncEsnAndUserIdImpl implements SyncEsnAndUserId {
    private Logger log = Logger.getLogger(this.getClass().getName());
    @Resource
    private CustomerEngineRelDao customerEngineRelDao;

    @Resource
    private OcrVehicleLicenseTMapper ocrVehicleLicenseTMapper;
    @Resource
    private DictionariesTDao dictionariesTDao;
    @Resource
    private UserTDao userTDao;
    @Resource
    private UserChannelTMapper userChannelTMapper;

    @Override
    public void asSyncEsnAndUserIdAddOne(String esn, String vinStr, Long userId,String drivingLicensePhotoUrl,String source,String inviteCode,String salesChannel) {
        if(StringUtils.isNumeric(esn) && esn.length() <= 8) {
            UserT user = userTDao.selectById(userId);
            List<UserChannelT> userChannelList = userChannelTMapper.getUserChannelListByUserId(userId);
            if(null != user){
                String serviceChannel = CollectionUtils.isNotEmpty(userChannelList) && StringUtils.isNotBlank(userChannelList.get(0).getServiceChannel()) ? userChannelList.get(0).getServiceChannel() : "1";
                String externalUserId = CollectionUtils.isNotEmpty(userChannelList) && StringUtils.isNotBlank(userChannelList.get(0).getExternalUserId()) ? userChannelList.get(0).getExternalUserId() : null;
                Integer channel  = StringUtils.isNotBlank(serviceChannel) ? Integer.valueOf(serviceChannel) : 1;
                Map<String, Object> mapReport = new HashMap<>();
                mapReport.put("ESN", esn);
                mapReport.put("plateNumber", vinStr);
                mapReport.put("userId",userId);
                if(channel != 1 && StringUtils.isNotBlank(externalUserId)){
                    mapReport.put("originChannel",channel);
                    mapReport.put("originUserId",externalUserId);
                } else {
                    mapReport.put("originChannel",1);
                    mapReport.put("originUserId",userId);
                }
                //是否有行驶证
                mapReport.put("drivingLicense", StringUtils.isNotBlank(drivingLicensePhotoUrl) ? 1 : 0);
                // 查询 用户绑车的ocr识别应用类型
                OcrVehicleLicenseT ocrVehicleLicenseT = new OcrVehicleLicenseT();
                ocrVehicleLicenseT.setEngineNumber(esn);
                OcrVehicleLicenseT ocrVehicleLicenseTParam = ocrVehicleLicenseTMapper.selectListLastByEsn(ocrVehicleLicenseT);
                mapReport.put("vehicleType", null!=ocrVehicleLicenseTParam ? ocrVehicleLicenseTParam.getVehicleType():"" );
                //来源
                mapReport.put("deviceSource", deviceSourceConvert(source));
                //渠道编号
                mapReport.put("deviceChannel", inviteCode);
                //渠道
                mapReport.put("deviceOwner", salesChannel);
                List<Map<String, Object>> list = new ArrayList<>();
                list.add(mapReport);
                this.asSyncEsnAndUserId(1, list, 1);
            }
        }
    }

    //来源转换
    @Override
    public Integer deviceSourceConvert(String source){
        Integer deviceSource = 11;//e路康明斯
        if(StringUtils.isNotBlank(source)){
           if(source.equals("2")){
               deviceSource = 21;//老友汇
           } else if(source.equals("3")){
                deviceSource = 31;//福康汇
            } else if(source.equals("4")){
               deviceSource = 41;//陕康云
           } else if(source.equals("DBU公众号")){
               deviceSource = 12;//DBU公众号
           }
        }
        return deviceSource;
    }

    @Override
    public void asSyncEsnAndUserIdUpdateOne(String esn, String vinStr, Long userId,String drivingLicensePhotoUrl,String source,String inviteCode,String salesChannel) {
        UserT user = userTDao.selectById(userId);
        List<UserChannelT> userChannelList = userChannelTMapper.getUserChannelListByUserId(userId);
        if(null != user){
            String serviceChannel = CollectionUtils.isNotEmpty(userChannelList) && StringUtils.isNotBlank(userChannelList.get(0).getServiceChannel()) ? userChannelList.get(0).getServiceChannel() : "1";
            String externalUserId = CollectionUtils.isNotEmpty(userChannelList) && StringUtils.isNotBlank(userChannelList.get(0).getExternalUserId()) ? userChannelList.get(0).getExternalUserId() : null;
            Integer channel  = StringUtils.isNotBlank(serviceChannel) ? Integer.valueOf(serviceChannel) : 1;
            Map<String, Object> mapReport = new HashMap<>();
            mapReport.put("ESN", esn);
            mapReport.put("plateNumber", vinStr);
            mapReport.put("userId",userId);
            if(channel != 1 && StringUtils.isNotBlank(externalUserId)){
                mapReport.put("originChannel",channel);
                mapReport.put("originUserId",externalUserId);
            } else {
                mapReport.put("originChannel",1);
                mapReport.put("originUserId",userId);
            }
            //是否有行驶证
            mapReport.put("drivingLicense", StringUtils.isNotBlank(drivingLicensePhotoUrl) ? 1 : 0);
            OcrVehicleLicenseT ocrVehicleLicenseT = new OcrVehicleLicenseT();
            ocrVehicleLicenseT.setEngineNumber(esn);
            OcrVehicleLicenseT ocrVehicleLicenseTParam = ocrVehicleLicenseTMapper.selectListLastByEsn(ocrVehicleLicenseT);
            mapReport.put("vehicleType", null!=ocrVehicleLicenseTParam ? ocrVehicleLicenseTParam.getVehicleType():"" );
            //来源
            mapReport.put("deviceSource", deviceSourceConvert(source));
            //渠道编号
            mapReport.put("deviceChannel", inviteCode);
            //渠道
            mapReport.put("deviceOwner", salesChannel);
            List<Map<String, Object>> list = new ArrayList<>();
            list.add(mapReport);
            this.asSyncEsnAndUserId(3, list,1);
        }
    }

    /**
     * 同步删除的方法
     * @param esn
     * @param userId
     */
    @Override
    public void asSyncEsnAndUserIdDelOne(String esn, Long userId) {
        UserT user = userTDao.selectById(userId);
        List<UserChannelT> userChannelList = userChannelTMapper.getUserChannelListByUserId(userId);
        if(null != user){
            String serviceChannel = CollectionUtils.isNotEmpty(userChannelList) && StringUtils.isNotBlank(userChannelList.get(0).getServiceChannel()) ? userChannelList.get(0).getServiceChannel() : "1";
            String externalUserId = CollectionUtils.isNotEmpty(userChannelList) && StringUtils.isNotBlank(userChannelList.get(0).getExternalUserId()) ? userChannelList.get(0).getExternalUserId() : null;
            Integer channel  = StringUtils.isNotBlank(serviceChannel) ? Integer.valueOf(serviceChannel) : 1;
            Map<String, Object> mapReport = new HashMap<>();
            mapReport.put("ESN", esn);
            mapReport.put("userId",userId);
            if(channel != 1 && StringUtils.isNotBlank(externalUserId)){
                mapReport.put("originChannel",channel);
                mapReport.put("originUserId",externalUserId);
            } else {
                mapReport.put("originChannel",1);
                mapReport.put("originUserId",userId);
            }
            List<Map<String, Object>> list = new ArrayList<>();
            list.add(mapReport);
            this.asSyncEsnAndUserId(2, list,1);
        }
    }

    /**
     * 调用月度报告的添加
     *
     * @param userId
     */
    @Override
    public void asSyncEsnAndUserIdAddByuserId(Long userId) {
        UserT user = userTDao.selectById(userId);
        if(null != user){
            List<CustomerEngineRelT> listByUserId = customerEngineRelDao.getListByUserId(userId);
            if (CollectionUtils.isNotEmpty(listByUserId)) {
                List<Map<String, Object>> paramList = this.getParamList(userId, listByUserId, true);
                this.asSyncEsnAndUserId(1, paramList,1);
            }
        }

    }

    /**
     * 封装请求的参数
     *
     * @param listByUserId
     * @return
     */
    public List<Map<String, Object>> getParamList(Long userId,List<CustomerEngineRelT> listByUserId, boolean isAddplateNumber) {
        UserT user = userTDao.selectById(userId);
        List<Map<String, Object>> list = new ArrayList<>();
        List<UserChannelT> userChannelList = userChannelTMapper.getUserChannelListByUserId(userId);
        if(null != user){
            String serviceChannel = CollectionUtils.isNotEmpty(userChannelList) && StringUtils.isNotBlank(userChannelList.get(0).getServiceChannel()) ? userChannelList.get(0).getServiceChannel() : "1";
            String externalUserId = CollectionUtils.isNotEmpty(userChannelList) && StringUtils.isNotBlank(userChannelList.get(0).getExternalUserId()) ? userChannelList.get(0).getExternalUserId() : null;
            Integer channel  = StringUtils.isNotBlank(serviceChannel) ? Integer.valueOf(serviceChannel) : 1;
            for (CustomerEngineRelT customerEngineRelT : listByUserId) {
                if(StringUtils.isNumeric(customerEngineRelT.getEsn()) && customerEngineRelT.getEsn().length() <= 8) {
                    Map<String, Object> mapReport = new HashMap<>();
                    mapReport.put("ESN", customerEngineRelT.getEsn());
                    mapReport.put("userId",userId);
                    if(channel != 1 && StringUtils.isNotBlank(externalUserId)){
                        mapReport.put("originChannel",channel);
                        mapReport.put("originUserId",externalUserId);
                    } else {
                        mapReport.put("originChannel",1);
                        mapReport.put("originUserId",userId);
                    }
                    //是否有行驶证
                    mapReport.put("drivingLicense", StringUtils.isNotBlank(customerEngineRelT.getDrivingLicensePhotoUrl()) ? 1 : 0);
                    if (isAddplateNumber) {
                        mapReport.put("plateNumber", customerEngineRelT.getVin());
                    }
                    OcrVehicleLicenseT ocrVehicleLicenseT = new OcrVehicleLicenseT();
                    ocrVehicleLicenseT.setEngineNumber(customerEngineRelT.getEsn());
                    OcrVehicleLicenseT ocrVehicleLicenseTParam = ocrVehicleLicenseTMapper.selectListLastByEsn(ocrVehicleLicenseT);
                    mapReport.put("vehicleType", null!=ocrVehicleLicenseTParam ? ocrVehicleLicenseTParam.getVehicleType():"" );
                    //来源
                    mapReport.put("deviceSource", deviceSourceConvert(customerEngineRelT.getServiceChannel()));
                    //渠道编号
                    mapReport.put("deviceChannel", customerEngineRelT.getInviteCode());
                    //渠道
                    mapReport.put("deviceOwner", customerEngineRelT.getSalesChannel());
                    list.add(mapReport);
                }
            }
        }
        return list;
    }

    /**
     * 调用月度报告的删除
     *
     * @param userId
     */
    @Override
    public void asSyncEsnAndUserIdDelByuserId(Long userId) {
        UserT user = userTDao.selectById(userId);
        if(null != user){
            List<CustomerEngineRelT> listByUserId = customerEngineRelDao.getListByUserId(userId);
            log.error("传入的参数 asSyncEsnAndUserIdDelByuserId"+ listByUserId);
            if (CollectionUtils.isNotEmpty(listByUserId)) {
                List<Map<String, Object>> paramList = this.getParamList(userId, listByUserId, false);
                this.asSyncEsnAndUserId(2, paramList,1);
            }
        }

    }

    /**
     * 调用月度报告的删除
     *
     * @param userId
     */
    @Override
    public void asSyncEsnAndUserIdDelByuserIdChannel(Long userId,String serviceChannel) {
        UserT user = userTDao.selectById(userId);
        if(null != user){
            List<CustomerEngineRelT> listByUserId = customerEngineRelDao.getListByUserId(userId);
            log.error("传入的参数 asSyncEsnAndUserIdDelByuserId"+ listByUserId);
            if (CollectionUtils.isNotEmpty(listByUserId)) {
                listByUserId = listByUserId.stream().filter(e -> StringUtils.isNotBlank(e.getServiceChannel()) && e.getServiceChannel().equals(serviceChannel)).collect(Collectors.toList());
                List<Map<String, Object>> paramList = this.getParamList(userId, listByUserId, false);
                this.asSyncEsnAndUserId(2, paramList,1);
            }
        }

    }

    /**
     * 调用月度报告的修改
     *
     * @param userId
     */
    @Override
    public void asSyncEsnAndUserIdUpdateByuserId(Long userId) {
        UserT user = userTDao.selectById(userId);
        if(null != user){
            List<CustomerEngineRelT> listByUserId = customerEngineRelDao.getListByUserId(userId);
            if (CollectionUtils.isNotEmpty(listByUserId)) {
                List<Map<String, Object>> paramList = this.getParamList(userId, listByUserId, false);
                this.asSyncEsnAndUserId(3, paramList,1);
            }
        }

    }

    public void asSyncEsnAndUserId(int type, List<Map<String, Object>> list,int channel) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("channel", channel);
        if (1 == type) {
            //添加
            paramMap.put("modify", new ArrayList<Map<String, Object>>());
            paramMap.put("delete", new ArrayList<Map<String, Object>>());
            paramMap.put("add", list);
        } else if (2 == type) {
            //删除
            paramMap.put("delete", list);
            paramMap.put("add", new ArrayList<Map<String, Object>>());
            paramMap.put("modify", new ArrayList<Map<String, Object>>());
        } else if (3 == type) {
            //修改
            paramMap.put("delete", new ArrayList<Map<String, Object>>());
            paramMap.put("add", new ArrayList<Map<String, Object>>());
            paramMap.put("modify", list);
        } else {
            log.error("传参错误：asSyncEsnAndUserId");
            return;
        }
        this.send(paramMap);
    }

    /**
     * @param addlist    添加的集合   不能为空 可以传空数组
     * @param updatelist 修改的集合   不能为空 可以传空数组
     * @param deletelist 删除的集合   不能为空 可以传空数组
     * @param channel    删除的渠道
     */
    @Override
    public void asSyncEsnAndUserIdList(List<Map<String, Object>> addlist, List<Map<String, Object>> updatelist, List<Map<String, Object>> deletelist, Integer channel) {
        if (CollectionUtils.isNotEmpty(addlist)) {
            for (Map<String, Object> stringObjectMap : addlist) {
                OcrVehicleLicenseT ocrVehicleLicenseT = new OcrVehicleLicenseT();
                ocrVehicleLicenseT.setEngineNumber(MapUtils.getString(stringObjectMap,"ESN"));
                OcrVehicleLicenseT ocrVehicleLicenseTParam = ocrVehicleLicenseTMapper.selectListLastByEsn(ocrVehicleLicenseT);
                stringObjectMap.put("vehicleType", null!=ocrVehicleLicenseTParam ? ocrVehicleLicenseTParam.getVehicleType():"" );
            }
        }
        if (CollectionUtils.isNotEmpty(updatelist)) {
            for (Map<String, Object> stringObjectMap : updatelist) {
                OcrVehicleLicenseT ocrVehicleLicenseT = new OcrVehicleLicenseT();
                ocrVehicleLicenseT.setEngineNumber(MapUtils.getString(stringObjectMap,"ESN"));
                OcrVehicleLicenseT ocrVehicleLicenseTParam = ocrVehicleLicenseTMapper.selectListLastByEsn(ocrVehicleLicenseT);
                stringObjectMap.put("vehicleType", null!=ocrVehicleLicenseTParam ? ocrVehicleLicenseTParam.getVehicleType():"" );
            }
        }
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("channel", channel);
        //添加
        paramMap.put("modify", updatelist);
        paramMap.put("delete", deletelist);
        paramMap.put("add", addlist);
        //调用发送的方法
        this.send(paramMap);
    }

    /**
     * 发送的方法
     *
     * @param paramMap
     */
    public void send(Map<String, Object> paramMap) {
        boolean success = false;
        try {
            //拼接 header 的参数
            //时间戳
            long currentTimeMillis = System.currentTimeMillis() / 1000;
            //token
            String token = this.getToken(currentTimeMillis, paramMap);
            log.info("月度报告参数：" + JSONObject.fromObject(paramMap).toString());
            String host = PropertiesUtil.getProperties("projectconfig.properties",
                    "cip.aws.host");
            String methon = PropertiesUtil.getProperties("projectconfig.properties",
                    "cip.aws.esnData");
            log.info("月度报告：地址：" + host + methon + "参数" + com.alibaba.fastjson.JSONObject.toJSONString(paramMap)
                    + "  token:" + token + "   currentTimeMillis:" + currentTimeMillis);
            Header timestampHeader = new BasicHeader("timestamp", "" + currentTimeMillis);
            Header tokenHeader = new BasicHeader("token", token);
            Header contentTypeHeader = new BasicHeader("Content-Type", "application/json");
            String result = HttpUtils.postJson(host + methon, JSONObject.fromObject(paramMap).toString(), new ResponseHandler<String>() {
                @Override
                public String handleResponse(HttpResponse response) throws ClientProtocolException, IOException {
                    if (response.getStatusLine().getStatusCode() == 200) {
                        HttpEntity httpEntity = response.getEntity();
                        return EntityUtils.toString(httpEntity);
                    }
                    return null;
                }
            }, timestampHeader, tokenHeader, contentTypeHeader);
            if (StringUtils.isNotBlank(result)) {
                com.alibaba.fastjson.JSONObject jsonObject = com.alibaba.fastjson.JSONObject.parseObject(result);
                Integer status = jsonObject.getInteger("status");
                if (null != status && status == 0) {
                    success = true;
                    log.info("调用:" + host + methon + "返回值成功");
                } else {
                    log.error("调用:" + host + methon + "返回值失败,返回值为" + jsonObject.toString() + "参数为:" + com.alibaba.fastjson.JSONObject.toJSONString(paramMap) + "token" + token);
                }
            } else {
                log.error("调用:" + host + methon + "返回值失败,参数为：" + com.alibaba.fastjson.JSONObject.toJSONString(paramMap) + "token" + token);
            }
        } catch (Exception e) {
            log.error(e.getMessage());
        } finally {
            if(!success){
                log.info("同步cipESN失败:" + paramMap.toString());
                List<Map<String, Object>> cipSyncList = dictionariesTDao.getDictionariesListByDTableName("cipSyncFail");
                if (CollectionUtils.isNotEmpty(cipSyncList)) {
                    for (Map<String, Object> dict : cipSyncList) {
                        try {
                            MailUtil.sendMail(MapUtils.getString(dict,"DValue"),"同步cipESN失败",paramMap.toString());
                        } catch (Exception e) {
                            log.error(MapUtils.getString(dict,"DValue") + "发送失败 原因：" + e.getMessage());
                        }
                    }
                }
            }
        }
    }

    public String getToken(long currentTimeMillis, Map<String, Object> paramMap) {
        JSONObject jsonObject = JSONObject.fromObject(paramMap);
//        String token = PublicTool.compute("cip" + jsonObject.toString() + currentTimeMillis);
        String token = "";
        try {
            token = PublicTool.md5(("cip" + jsonObject.toString() + currentTimeMillis).getBytes("UTF-8"));
        } catch (UnsupportedEncodingException e) {
            log.error("月度报告获取token失败");
            log.error(e.getMessage());
        }
        return token;
    }
}
